package com.ddd.core.api;

import com.ddd.core.constants.enums.ApiCodeEnum;
import com.ddd.core.exception.BizException;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;

import java.io.Serializable;
import java.util.Optional;

/**
 * 接口返回api
 *
 * @author zhongwenbin
 * @date 2023/6/24 22:22
 */
@Data
@AllArgsConstructor
@Accessors(chain = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ApiResult<T> implements Serializable {
    static final long serialVersionUID = 1L;
    /**
     * 状态码
     */
    String code;
    /**
     * 响应消息
     */
    String message;
    /**
     * 结果集
     */
    T data;
    /**
     * 内部消息
     */
    String innerMsg;


    public ApiResult(IResultCode resultCode) {
        IResultCode errorCode = Optional.ofNullable(resultCode).orElse(ApiCodeEnum.FAILED);
        this.code = errorCode.getCode();
        this.message = errorCode.getMessage();
        this.innerMsg = errorCode.getInnerMsg();
    }

    public static <T> ApiResult<T> ok() {
        return new ApiResult<>(ApiCodeEnum.SUCCESS);
    }

    public static <T> ApiResult<T> ok(T data) {
        return restResult(data, ApiCodeEnum.SUCCESS);
    }

    public static <T> ApiResult<T> ok(T data, String message) {
        ApiCodeEnum success = ApiCodeEnum.SUCCESS;
        return restResult(data, success.getCode(), message, message);
    }


    static <T> ApiResult<T> ok(String code, String message, T data) {
        return restResult(data, code, message, message);
    }


    public static <T> ApiResult<T> failed() {
        return new ApiResult<>(ApiCodeEnum.FAILED);
    }

    public static <T> ApiResult<T> failed(String message) {
        ApiCodeEnum failed = ApiCodeEnum.FAILED;
        return restResult(null, failed.getCode(), message, message);
    }


    public static <T> ApiResult<T> failed(String code, String message) {

        return restResult(null, code, message, message);
    }

    public static <T> ApiResult<T> failed(IResultCode resultCode) {
        return ApiResult.restResult(null, resultCode);
    }

    @SuppressWarnings(value = "unchecked")
    public static <T> ApiResult<T> failed(BizException exception) {
        return new ApiResult<>(exception.getCode(), exception.getMessage(),
                (T) exception.getData(), exception.getInnerMsg());
    }

    public static <T> ApiResult<T> restResult(T data, IResultCode resultCode) {
        return restResult(data, resultCode.getCode(), resultCode.getMessage(),
                resultCode.getInnerMsg());
    }

    private static <T> ApiResult<T> restResult(T data, String code, String message,
                                               String innerMsg) {
        return new ApiResult<>(code, message, data, innerMsg);
    }


}
